<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Observer 模式</title>
</head>

<body>
    <button id="addNewOberver">Add new observer checkbox</button>
    <input type="checkbox" id="mainCheckbox">
    <div class="observersContainer"></div>
    <script>
        function ObserverList() {
            this.observerList = [];
        }

        ObserverList.prototype.Add = function(obj) {
            return this.observerList.push(obj);
        }

        ObserverList.prototype.Empty = function() {
            this.observerList = [];
        }

        ObserverList.prototype.Count = function() {
            return this.observerList.length;
        }

        ObserverList.prototype.Get = function(index) {
            if (index > -1 && index < this.observerList.length) {
                return this.observerList[index];
            }
        }

        ObserverList.prototype.Insert = function(obj, index) {
            let pointer = -1;
            if (index === 0) {
                this.observerList.unshift(obj);
                pointer = index;
            } else if (index === this.observerList.length) {
                this.observerList.push(obj);
                pointer = index;
            }
            return pointer;
        }

        ObserverList.prototype.IndexOf = function(obj, startIndex) {
            let i = startIndex,
                pointer = -1;
            while (i < this.observerList.length) {
                if (this.observerList[i] === obj) {
                    pointer = i;
                }
                i++;
            }
            return pointer;
        }

        ObserverList.prototype.RemoveIndexAt = function(index) {
            if (index === 0) {
                this.observerList.shift();
            } else if (index === this.observerList.length - 1) {
                this.observerList.pop()
            }
        }

        function extend(obj, extension) {
            for (let key in obj) {
                console.log(key)
                extension[key] = obj[key];
            }
        }

        function Subject() {
            this.obervers = new ObserverList();
        }

        Subject.prototype.AddObserver = function(observer) {
            this.obervers.Add(observer);
        }

        Subject.prototype.RemoveObserver = function(observer) {
            this.obervers.RemoveIndexAt(this.obervers.IndexOf(observer, 0));
        }

        Subject.prototype.Notify = function(context) {
            let observerCoun = this.obervers.Count();
            for (let i = 0; i < observerCoun; i++) {
                this.obervers.Get(i).Update(context);
            }
        }

        function Observer() {
            this.Update = function() {

            }
        }

        let controlCheckbox = document.querySelector("#mainCheckbox");
        let addBtn = document.querySelector("#addNewOberver");
        let container = document.querySelector(".observersContainer");

        // Subject实例
        // 利用Subject扩展controlCheckbox
        extend(new Subject(), controlCheckbox)

        // 点击checkbox会触发通知到观察者上
        controlCheckbox['onclick'] = function() {
            controlCheckbox.Notify(controlCheckbox.checked);
        }
        addBtn['onclick'] = AddNewObserver;

        function AddNewObserver() {
            let check = document.createElement('input');
            check.type = "checkbox";
            extend(new Observer(), check);
            check.Update = function(value) {
                this.checked = value;
            }
            controlCheckbox.AddObserver(check);
            container.append(check);
        }
    </script>
</body>

</html>